﻿#include "mode1_standard.hpp"
#include "mode_data.hpp"
#include "../../liblive2d/include/catlive2d.hpp"
#include "../../libcat/include/cat-window.hpp"
#include "../../libcat/include/util/jsoncpp.cpp"
#include "../../libcat/include/cat-audio.hpp"
namespace{
	standard * s_instance = NULL;

	POINT point;

	std::tuple<double, double> bezier(double ratio, std::vector<double>& points, int length)
	{
		double fact[22] = { 0.001, 0.001, 0.002, 0.006, 0.024, 0.12, 0.72, 5.04, 40.32, 362.88, 3628.8, 39916.8, 479001.6, 6227020.8, 87178291.2, 1307674368.0, 20922789888.0, 355687428096.0, 6402373705728.0, 121645100408832.0, 2432902008176640.0, 51090942171709440.0 };
		int nn = (length / 2) - 1;
		double xx = 0;
		double yy = 0;

		for (int point = 0; point <= nn; point++)
		{
			double tmp = fact[nn] / (fact[point] * fact[nn - point]) * pow(ratio, point) * pow(1 - ratio, nn - point);
			xx += points[2 * point] * tmp;
			yy += points[2 * point + 1] * tmp;
		}
		return std::make_tuple(xx / 1000, yy / 1000);
	}

	//根据参数得到一个手的数组
	static void setrighthand(double x, double y, double* pmpos0, double* pmpos1, std::vector<double>* ppss2, double dx, double dy)
	{
		// initializing pss and pss2 (kuvster's magic)
		int oof = 6;
		std::vector<double> pss = { 211.0, 159.0 };
		double dist = hypot(211 - x, 159 - y);
		double centreleft0 = 211 - 0.7237 * dist / 2;
		double centreleft1 = 159 + 0.69 * dist / 2;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 211, 159, centreleft0, centreleft1, x, y };
			std::tie(p0, p1) = bezier(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(x);
		pss.push_back(y);
		double a = y - centreleft1;
		double b = centreleft0 - x;
		double le = hypot(a, b);
		a = x + a / le * 60;
		b = y + b / le * 60;
		int a1 = 258;
		int a2 = 228;
		dist = hypot(a1 - a, a2 - b);
		double centreright0 = a1 - 0.6 * dist / 2;
		double centreright1 = a2 + 0.8 * dist / 2;
		int push = 20;
		double s = x - centreleft0;
		double t = y - centreleft1;
		le = hypot(s, t);
		s *= push / le;
		t *= push / le;
		double s2 = a - centreright0;
		double t2 = b - centreright1;
		le = hypot(s2, t2);
		s2 *= push / le;
		t2 *= push / le;
		for (double i = 1; i < oof; i++)
		{
			double p0;
			double p1;
			std::vector<double> bez = { x, y, x + s, y + t, a + s2, b + t2, a, b };
			std::tie(p0, p1) = bezier(i / oof, bez, 8);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a);
		pss.push_back(b);
		for (double i = oof - 1; i > 0; i--)
		{
			double p0;
			double p1;
			std::vector<double> bez = { 1.0 * a1, 1.0 * a2, centreright0, centreright1, a, b };
			std::tie(p0, p1) = bezier(i / oof, bez, 6);
			pss.push_back(p0);
			pss.push_back(p1);
		}
		pss.push_back(a1);
		pss.push_back(a2);
		*pmpos0 = (a + x) / 2 - 52 - 15;
		*pmpos1 = (b + y) / 2 - 34 + 5;


		const int iter = 25;

		*ppss2 = { pss[0] + dx, pss[1] + dy };
		for (double i = 1; i < iter; i++)
		{
			double p0;
			double p1;
			std::tie(p0, p1) = bezier(i / iter, pss, 38);
			ppss2->push_back(p0 + dx);
			ppss2->push_back(p1 + dy);
		}
		ppss2->push_back(pss[36] + dx);
		ppss2->push_back(pss[37] + dy);
	}

}

standard* standard::GetInstance()
{
	if (s_instance == NULL)
	{
		s_instance = new standard();
	}
	return s_instance;
}

void standard::ReleaseInstance()
{
	if (s_instance != NULL)
	{
		delete s_instance;
	}
	s_instance = NULL;
}

void standard::Init(Json::Value cfg)
{	
	renderWindowWidth = cfg["decoration"]["window_size"][0].asInt();
	renderWindowHeight = cfg["decoration"]["window_size"][1].asInt();
	cat_set_gui_size(renderWindowWidth, renderWindowHeight);

	std::string standard_module_path;
	for (auto entry = cfg["plugins"]["mode_ex"].begin(); entry != cfg["plugins"]["mode_ex"].end(); entry++)
	{
		if ((*entry)["module_id"].asInt() == 1) {
			standard_module_path =(*entry)["module_data_path"].asString();
			break;
		}
	}
	const char* data = ModeData::LoadFileAsBytes(standard_module_path.c_str());
	if (data == NULL)
	{
		isInit = false;
		return;
	}

	JSONCPP_STRING error;
	Json::CharReaderBuilder json_builder;
	Json::Value root;
	Json::CharReader* json_reader = json_builder.newCharReader();
	bool parsingSuccessful = json_reader->parse(data, data + strlen(data), &root, &error);

	if (!parsingSuccessful) {
		return;
	}
	delete json_reader;
	delete data;

	key_clock.restart();

	offset_x = root["decoration"]["offsetX"][0].asInt();
	offset_y = root["decoration"]["offsetY"][0].asInt();
	scale = root["decoration"]["scalar"][0].asDouble();

	mouse_leftkey_value = root["standard"]["mouse_left"];
	mouse_rightkey_value = root["standard"]["mouse_right"];
	mouse_sidekey_value = root["standard"]["mouse_side"];

	RECT desktop;
	const HWND h_desktop = GetDesktopWindow();
	GetWindowRect(h_desktop, &desktop);
	horizontal = desktop.right;
	vertical = desktop.bottom;

	if (root["workarea"]["workarea"].asBool()) {
		letter_x = root["workarea"]["top_left"][0].asInt();
		letter_y = root["workarea"]["top_left"][1].asInt();
		s_width = root["workarea"]["right_bottom"][0].asInt() - letter_x;
		s_height = root["workarea"]["right_bottom"][1].asInt() - letter_y;

	}
	else {
		s_width = horizontal;
		s_height = vertical;
		letter_x = 0;
		letter_y = 0;
	}
	
	std::string mode_path = standard_module_path.substr(0, standard_module_path.find_last_of("/")+1);
	if (mode_path.size() == 0) {
		mode_path = standard_module_path.substr(0, standard_module_path.find_last_of("\\") + 1);
	}

	if (!atextex.loadFromFile(mode_path+"arm.png"))
	{
		ModeData::error_msg("File not successfully loaded");
	}
	up.setTexture(ModeData::load_texture2(mode_path+"up.png"));
	cat.setTexture(ModeData::load_texture2(mode_path + "cat.png"));

	bg.setTexture(ModeData::load_texture2(mode_path + "mousebg.png"));
	device.setTexture(ModeData::load_texture2(mode_path + "mouse.png"), true);
	mouse_left.setTexture(ModeData::load_texture2(mode_path + "mouse_left.png"), true);
	mouse_right.setTexture(ModeData::load_texture2(mode_path + "mouse_right.png"), true);
	mouse_side.setTexture(ModeData::load_texture2(mode_path + "mouse_side.png"), true);
	
	int index = 0;
	while (!root["standard"]["hand"][index].isNull()) {
		std::string imgpath = mode_path + "hand/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["standard"]["hand"][index][key_index].isNull()) {
			int keycode = root["standard"]["hand"][index][key_index].asInt();
			left_hands_down[imgpath].keys.push_back(keycode); 
			states[keycode] = false;
			key_index++;
		}
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["standard"]["keyboard"][index].isNull()) {
		std::string imgpath = mode_path + "keyboard/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["standard"]["keyboard"][index][key_index].isNull()) {
			int keycode = root["standard"]["keyboard"][index][key_index].asInt();
			keys[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}	
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["standard"]["face"][index].isNull()) {
		std::string imgpath = mode_path + "face/" + std::to_string(index) + ".png";
		int key_index = 0;
		while (!root["standard"]["face"][index][key_index].isNull()) {
			int keycode = root["standard"]["face"][index][key_index].asInt();
			faces[imgpath].keys.push_back(keycode);	
			states[keycode] = false;		
			key_index++;
		}	
		ModeData::load_texture2(imgpath);
		index++;
	}

	index = 0;
	while (!root["standard"]["sounds"][index].isNull()) {
		std::string imgpath = mode_path + "sounds/" + std::to_string(index) + ".flac";
		int key_index = 0;
		while (!root["standard"]["sounds"][index][key_index].isNull()) {
			int keycode = root["standard"]["sounds"][index][key_index].asInt();
			sounds[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}		
		index++;
	}
	
	index = 0;
	while (!root["standard"]["l2d_motion"][index].isNull()) {
		std::string imgpath = std::to_string(index);
		int key_index = 0;
		while (!root["standard"]["l2d_motion"][index][key_index].isNull()) {
			int keycode = root["standard"]["l2d_motion"][index][key_index].asInt();
			motions[imgpath].keys.push_back(keycode);			
			states[keycode] = false;
			key_index++;
		}
		index++;
	}

	index = 0;
	while (!root["standard"]["l2d_expression"][index].isNull()) {
		std::string imgpath = std::to_string(index);
		int key_index = 0;
		while (!root["standard"]["l2d_expression"][index][key_index].isNull()) {
			int keycode = root["standard"]["l2d_expression"][index][key_index].asInt();
			expression[imgpath].keys.push_back(keycode);
			states[keycode] = false;
			key_index++;
		}
		index++;
	}

	device.setScale(scale, scale);
	mouse_left.setScale(scale, scale);
	mouse_right.setScale(scale, scale);
	mouse_side.setScale(scale, scale);

	std::string l2dmodelPath = mode_path + "cat_model/";
	cat_live2d_load_model(l2dmodelPath.c_str(), "cat.model3.json");

	isInit = true;
	
	Updata(cfg);
}

void standard::Updata(Json::Value cfg)
{
	renderWindowWidth= cfg["decoration"]["window_size"][0].asInt();
	renderWindowHeight= cfg["decoration"]["window_size"][1].asInt();
	
	renderTexture.create(renderWindowWidth, renderWindowHeight,false);
	renderTexture.setSmooth(true);
	renderSprite.setTexture(renderTexture.getTexture());
	renderSprite.setTextureRect(sf::IntRect(sf::Vector2i(0,0),sf::Vector2i(renderTexture.getSize().x, renderTexture.getSize().y)));

	red_value = cfg["decoration"]["armLineColor"][0].asInt();
	green_value = cfg["decoration"]["armLineColor"][1].asInt();
	blue_value = cfg["decoration"]["armLineColor"][2].asInt();

	hand_offset_x = cfg["decoration"]["hand_offset"][0].asInt();
	hand_offset_y = cfg["decoration"]["hand_offset"][1].asInt();

	mousespeed = cfg["main_decoration"]["mouse_speed"].asFloat();
	is_mouse_force_move = cfg["main_decoration"]["mouse_force_move"].asBool();
	mouse_horizontal_flip = cfg["main_decoration"]["mouse_horizontal_flip"].asBool();
	mouse_vertical_flip = cfg["main_decoration"]["mouse_vertical_flip"].asBool();

	motion_keep = cfg["main_decoration"]["motion_keep"].asBool();
	sound_keep = cfg["main_decoration"]["sound_keep"].asBool();

	isLive2d = cfg["main_decoration"]["l2d"].asBool();

	if (isLive2d) {		

		l2d_correct = cfg["decoration"]["l2d_correct"].asFloat();
		l2d_offset_x = cfg["decoration"]["l2d_offset"][0].asFloat();
		l2d_offset_y = cfg["decoration"]["l2d_offset"][1].asFloat();

		float speed = cfg["main_decoration"]["l2d_spead"].asFloat();
		l2d_random_motion = cfg["main_decoration"]["l2d_random_motion"].asBool();
		l2d_random_expression = cfg["main_decoration"]["l2d_random_expression"].asBool();
		cat_live2d_translate(l2d_offset_x, l2d_offset_y);
		cat_live2d_scale(l2d_correct, l2d_correct);
		cat_live2d_speed(speed);
		cat_live2d_set_random_motion(l2d_random_motion, l2d_random_expression);

		cat_live2d_resize(renderWindowWidth, renderWindowHeight);
	}

	cat_audio_set_silent(cfg["main_decoration"]["silent"].asBool());
}

void standard::Draw(void* _window)
{
	cat_window* window = (cat_window*)_window;

	if (isInit) {

		renderTexture.clear(sf::Color(0,0,0,0));
		
		if (isLive2d) {	
			renderTexture.draw(bg);
			cat_live2d_run(NULL);
			drawKey(renderTexture);
			drawHand(renderTexture);
			drawFace(renderTexture);
			playMotion();
			playExpression();		
		}
		else {
			drawCat(renderTexture);
			drawFace(renderTexture);
			drawKey(renderTexture);
			drawHand(renderTexture);
		}
		playSound();
		

		renderTexture.display();
		window->window->draw(renderSprite);		
	}	
}

void standard::Release()
{
	ModeData::clear_holder();
	isInit = false;
	states.clear();

	cat_live2d_release_model();

	left_hands_down.clear();
	keys.clear();
	faces.clear();
	sounds.clear();
	motions.clear();
	expression.clear();
}

void standard::OnMouseMove(int x, int y)
{
	if (isInit&&!is_mouse_force_move) {
		float cx = static_cast<float>(x) / static_cast<float>(horizontal);
		float cy = static_cast<float>(y) / static_cast<float>(vertical);
		if (mouse_horizontal_flip) {
			cx = 1.0 - cx;
			point.x = horizontal-x;
		}
		else
			point.x = x;
		if (mouse_vertical_flip) 
		{
			cy = 1.0 - cy;
			point.y = vertical-y;
		}		
		else 
			point.y = y;

		cat_live2d_on_mouse_move_callback(1.-cx, 1.-cy); 			
	}
}

void standard::OnForceMouseMove(int x, int y)
{
	if (isInit && is_mouse_force_move) {
		point.x += x*mousespeed;
		point.y += y* mousespeed;

		if (point.x < letter_x)point.x = letter_x;
		if (point.x > (s_width + letter_x))point.x = s_width + letter_x;
		if (point.y < letter_y)point.y = letter_y;
		if (point.y > (s_width + letter_x))point.y = s_height + letter_y;
		mouse_x = ((double)point.x - letter_x) / s_width;
		mouse_y = ((double)point.y - letter_y) / s_height;

		mouse_x = std::min(mouse_x, 1.0);
		mouse_x = std::max(mouse_x, 0.0);
		mouse_y = std::min(mouse_y, 1.0);
		mouse_y = std::max(mouse_y, 0.0);

		if (mouse_horizontal_flip)
			mouse_x = 1 - mouse_x;
		if (mouse_vertical_flip)
			mouse_y = 1 - mouse_y;

		cat_live2d_on_mouse_move_callback(1.-mouse_x, 1.-mouse_y);
	}
}

void standard::OnMouseClick(const cat_mouse_click_event* event, bool key_up)
{
	if (isInit) {
		cat_live2d_on_mouse_click_callback(event, key_up);
	}
}

void standard::OnKeyPress(const int vk, bool key_up)
{
	if (states.find(vk) != states.end()) {
			states[vk] = !key_up;
	}
}

standard::standard()
{
	
}

standard::~standard()
{
	
}

void standard::drawCat(sf::RenderTexture &window)
{
	window.draw(cat);

	window.draw(bg);

	double x, y;
	if (is_mouse_force_move)
	{
		x = -97 * mouse_x + 44 * mouse_y + 184;
		y = -76 * mouse_x - 40 * mouse_y + 324;
	}
	else
	{
		double fx = ((double)point.x - letter_x) / s_width;
		double fy = ((double)point.y - letter_y) / s_height;
		fx = std::min(fx, 1.0);
		fx = std::max(fx, 0.0);
		fy = std::min(fy, 1.0);
		fy = std::max(fy, 0.0);
		x = -97 * fx + 44 * fy + 184;
		y = -76 * fx - 40 * fy + 324;
	}

	double mpos0, mpos1;
	double dx = -38;
	double dy = -50;
	std::vector<double>pss2;
	//计算右手的贝塞尔曲线数组
	setrighthand(x, y, &mpos0, &mpos1, &pss2, dx, dy);

	//对右手进行位置处理
	for (int i = 0; i < 26; i++)
	{
		pss2[i * 2] += hand_offset_x;
		pss2[i * 2 + 1] += hand_offset_y;
	}
	device.setPosition(mpos0 + dx + offset_x + hand_offset_x, mpos1 + dy + offset_y + hand_offset_y);
	mouse_left.setPosition(mpos0 + dx + offset_x + hand_offset_x, mpos1 + dy + offset_y + hand_offset_y);
	mouse_right.setPosition(mpos0 + dx + offset_x + hand_offset_x, mpos1 + dy + offset_y + hand_offset_y);
	mouse_side.setPosition(mpos0 + dx + offset_x + hand_offset_x, mpos1 + dy + offset_y + hand_offset_y);

	// drawing mouse

		window.draw(device);
		for (Json::Value& v : mouse_leftkey_value)
			if (GetKeyState(v.asInt()) & 0x8000)
			{
				window.draw(mouse_left);
				break;
			}
		for (Json::Value& v : mouse_rightkey_value)
			if (GetKeyState(v.asInt()) & 0x8000)
			{
				window.draw(mouse_right);
				break;
			}
		for (Json::Value& v : mouse_sidekey_value)
			if (GetKeyState(v.asInt()) & 0x8000)
			{
				window.draw(mouse_side);
				break;
			}

	//设置右手形状，绘制右手纹理
	sf::ConvexShape fill(26);
	for (int i = 0; i < 26; i++)
	{
		fill.setPoint(i, sf::Vector2f(pss2[i * 2], pss2[i * 2 + 1]));
	}
	fill.setTexture(&atextex);
	window.draw(fill);

	drawline(window,pss2, red_value, green_value, blue_value);
}

//根据数组绘制曲线
void standard::drawline(sf::RenderTexture &window, std::vector<double> pss2, int red_value, int green_value, int blue_value)
{
	// drawing first arm arc
	int shad = 77;
	sf::VertexArray edge(sf::TriangleStrip, 52);
	double width = 7;
	sf::CircleShape circ(width / 2);
	circ.setFillColor(sf::Color(red_value, green_value, blue_value, shad));
	circ.setPosition(pss2[0] - width / 2, pss2[1] - width / 2);

	window.draw(circ);
	for (int i = 0; i < 50; i += 2)
	{
		double vec0 = pss2[i] - pss2[i + 2];
		double vec1 = pss2[i + 1] - pss2[i + 3];
		double dist = hypot(vec0, vec1);
		edge[i].position = sf::Vector2f(pss2[i] + vec1 / dist * width / 2, pss2[i + 1] - vec0 / dist * width / 2);
		edge[i + 1].position = sf::Vector2f(pss2[i] - vec1 / dist * width / 2, pss2[i + 1] + vec0 / dist * width / 2);
		edge[i].color = sf::Color(0, 0, 0, shad);
		edge[i + 1].color = sf::Color(0, 0, 0, shad);
		width -= 0.08;
	}
	double vec0 = pss2[50] - pss2[48];
	double vec1 = pss2[51] - pss2[49];
	double dist = hypot(vec0, vec1);
	edge[51].position = sf::Vector2f(pss2[50] + vec1 / dist * width / 2, pss2[51] - vec0 / dist * width / 2);
	edge[50].position = sf::Vector2f(pss2[50] - vec1 / dist * width / 2, pss2[51] + vec0 / dist * width / 2);
	edge[50].color = sf::Color(red_value, green_value, blue_value, shad);
	edge[51].color = sf::Color(red_value, green_value, blue_value, shad);
	window.draw(edge);
	circ.setRadius(width / 2);
	circ.setPosition(pss2[50] - width / 2, pss2[51] - width / 2);
	window.draw(circ);

	// drawing second arm arc
	sf::VertexArray edge2(sf::TriangleStrip, 52);
	width = 6;
	sf::CircleShape circ2(width / 2);
	circ2.setFillColor(sf::Color(red_value, green_value, blue_value));
	circ2.setPosition(pss2[0] - width / 2, pss2[1] - width / 2);
	window.draw(circ2);
	for (int i = 0; i < 50; i += 2)
	{
		vec0 = pss2[i] - pss2[i + 2];
		vec1 = pss2[i + 1] - pss2[i + 3];
		double dist = hypot(vec0, vec1);
		edge2[i].position = sf::Vector2f(pss2[i] + vec1 / dist * width / 2, pss2[i + 1] - vec0 / dist * width / 2);
		edge2[i + 1].position = sf::Vector2f(pss2[i] - vec1 / dist * width / 2, pss2[i + 1] + vec0 / dist * width / 2);
		edge2[i].color = sf::Color(red_value, green_value, blue_value);
		edge2[i + 1].color = sf::Color(red_value, green_value, blue_value);
		width -= 0.08;
	}
	vec0 = pss2[50] - pss2[48];
	vec1 = pss2[51] - pss2[49];
	dist = hypot(vec0, vec1);
	edge2[51].position = sf::Vector2f(pss2[50] + vec1 / dist * width / 2, pss2[51] - vec0 / dist * width / 2);
	edge2[50].position = sf::Vector2f(pss2[50] - vec1 / dist * width / 2, pss2[51] + vec0 / dist * width / 2);
	edge2[50].color = sf::Color(red_value, green_value, blue_value);
	edge2[51].color = sf::Color(red_value, green_value, blue_value);
	window.draw(edge2);
	circ2.setRadius(width / 2);
	circ2.setPosition(pss2[50] - width / 2, pss2[51] - width / 2);
	window.draw(circ2);
}

void standard::drawKey(sf::RenderTexture &window)
{
	for (auto entry = keys.begin(); entry != keys.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow == true) {
			sf::Sprite key;
			key.setTexture(ModeData::load_texture2((*entry).first));
			window.draw(key);
		}
	}
}

void standard::drawHand(sf::RenderTexture & window)
{
	bool HandUp = true;
	std::string whichHand;
	for (auto entry = left_hands_down.begin(); entry != left_hands_down.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		if (flag && !(*entry).second.isShow) {
			(*entry).second.record = key_clock.getElapsedTime();
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow)
		{
			if (whichHand.empty()) {
				whichHand = (*entry).first;
			}
			if (left_hands_down[whichHand].record < (*entry).second.record)
			{
				whichHand = (*entry).first;
			}	
			HandUp = false;
		}		
	}
	cat_live2d_on_left_hand_down_callback(HandUp);

	if (!whichHand.empty()&&left_hands_down[whichHand].isShow) {
		sf::Sprite hand;
		hand.setTexture(ModeData::load_texture2(whichHand));
		window.draw(hand);
	}

	if (!isLive2d&&HandUp)
		window.draw(up);
}

void standard::drawFace(sf::RenderTexture &window)
{
	for (auto entry = faces.begin(); entry != faces.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}		
		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if(motion_keep){
			if ((*entry).second.isShow != (*entry).second.isLastShow) {
				if((*entry).second.isLastShow)
					(*entry).second.LastShowCount++;
				(*entry).second.isLastShow = (*entry).second.isShow;				
			}
			
			if ((*entry).second.LastShowCount % 2) {
				sf::Sprite key;
				key.setTexture(ModeData::load_texture2((*entry).first));
				window.draw(key);
			}
		}
		else if ((*entry).second.isShow) {
			sf::Sprite key;
			key.setTexture(ModeData::load_texture2((*entry).first));
			window.draw(key);
		}
	}
}

void standard::playSound()
{
	for (auto entry = sounds.begin(); entry != sounds.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		flag ? (*entry).second.isShow = true : (*entry).second.isShow = false;

		if ((*entry).second.isShow != (*entry).second.isLastShow) {
			if (!(*entry).second.isLastShow)
				(*entry).second.LastShowCount++;
			(*entry).second.isLastShow = (*entry).second.isShow;
		}

		if ((*entry).second.LastShowCount % 2) {
			if((*entry).second.isShow)
				cat_play_sound((*entry).first.c_str(), sound_keep);
			(*entry).second.LastShowCount++;
		}		
	}
}

void standard::playMotion()
{
	for (auto entry = motions.begin(); entry != motions.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}
		if (flag == true) {
			cat_live2d_play_motion("CAT_motion", std::stoi((*entry).first));
		}
	}
}

void standard::playExpression()
{
	for (auto entry = expression.begin(); entry != expression.end(); entry++) {
		bool flag = true;
		for (auto key_state = (*entry).second.keys.begin(); key_state != (*entry).second.keys.end(); key_state++)
		{
			flag &= states[(*key_state)];
		}

		if (motion_keep) {
			if (flag != (*entry).second.isLastShow) {
				if (flag)
				{
					(*entry).second.LastShowCount++;
				}
				(*entry).second.isLastShow = flag;
			}			

			if ((*entry).second.LastShowCount % 2) {
				if (flag&&!(*entry).second.isShow)
				{	
					for (auto entry2 = expression.begin(); entry2 != expression.end(); entry2++) {
						(*entry2).second.isShow = false;
					}
					(*entry).second.isShow = true; 
					cat_live2d_set_expression_by_id(std::stoi((*entry).first));									
				}
				else if (flag)
				{
					cat_live2d_set_expression_by_id(0); 
					(*entry).second.isShow = false;
				}				
				(*entry).second.LastShowCount++;
			}
		}
		else 
		{
			if (flag) {
				cat_live2d_set_expression_by_id(std::stoi((*entry).first));	
				(*entry).second.isShow = true;
			}
			else if ((*entry).second.isShow)
			{
				(*entry).second.isShow = false; 
				cat_live2d_set_expression_by_id(0); 
			}

		}		
	}	
}



